using System;
using System.Collections.Generic;
using UnityEngine;

public class DownLoadProgress
{
    public int Max;
    public int DownloadedCount;
}
public class DownLoadedInfo
{
    /// <summary>
    /// �ظ���ǰ������ɵ��ļ���Ϣ
    /// </summary>
    public stDownLoadFileInfo FileInfo;
    /// <summary>
    /// �Ƿ����سɹ�
    /// </summary>
    public bool Success;
    /// <summary>
    /// ��������
    /// </summary>
    public byte[] data;
}
/// <summary>
/// ���������ļ�
/// </summary>
public class HFDownLoadGroup : IHFRecycle
{
    /// <summary>
    /// �ȴ�ִ���ļ�
    /// </summary>
    /// 
    private HFScriptMemPool<HFDownLoadAssetHandle> m_MemPool;
   
    /// <summary>
    /// �ȴ������ļ�
    /// </summary>
    private List<stDownLoadFileInfo> m_WaitDownloadFileList;

    private GameObject m_RootGameObject;
    /// <summary>
    /// �ļ�������ɻص�
    /// </summary>
    private Action<DownLoadedInfo> On_DownLoadCallBack;
    /// <summary>
    /// ���ؽ���
    /// </summary>
    private Action<DownLoadProgress> On_DownLoadProgress;
    /// <summary>
    ///  �����������
    /// </summary>
    private Action<HFDownLoadGroup> On_Taskfinish;
    /// <summary>
    /// ����߳�
    /// </summary>
    private int m_MaxTask;
    /// <summary>
    /// ��������
    /// </summary>
    private int MaxFailedCount = 5;

    /// <summary>
    /// ����ʧ�ܵ��ļ�
    /// </summary>
    public List<stDownLoadFileInfo> FailedFile { get; private set; }
    /// <summary>
    /// �����ص�����
    /// </summary>
    public int DownloadedCount { get; private set; }
    /// <summary>
    /// ȫ����Ҫ���ص���
    /// </summary>
    public int MaxDownloadCount { get; private set; }
    /// <summary>
    /// ������Ľ�������
    /// </summary>
    private int m_CanUseTaskCount
    {
        get { return m_MaxTask - m_MemPool.UsingCount; }
    }
    /// <summary>
    ///  ֪ͨ ��Ҫ���صĵط� �� �ɹ� ʧ�� ���ȣ�ȫ���������֪ͨDownLoadManager �������
    /// </summary>
    /// <param name="rootobj"></param>
    /// <param name="maxTask"></param>
    public void Init(GameObject rootobj, int maxTask ,Action<HFDownLoadGroup> taskfinish)
    {
        this.On_Taskfinish = taskfinish;
        m_RootGameObject = new GameObject("DownLoadGroup" + this.GetHashCode());
        m_RootGameObject.transform.SetParent(rootobj.transform);
        m_MemPool = new HFScriptMemPool<HFDownLoadAssetHandle>();
        FailedFile = new List<stDownLoadFileInfo>();
        m_WaitDownloadFileList = new List<stDownLoadFileInfo>();
        m_MaxTask = maxTask;
    }
    /// <summary>
    /// �������
    /// </summary>
    /// <param name="downLoad">����</param>
    /// <param name="downloadcallback">������ɻص�</param>
    /// <param name="downloadprogress">���ؽ��Ȼص�</param>
    public void AddDownLoadTaskList(List<stDownLoadFileInfo> downLoad, Action<DownLoadedInfo> downloadcallback, Action<DownLoadProgress> downloadprogress)
    {
        this.On_DownLoadCallBack = downloadcallback;
        this.On_DownLoadProgress = downloadprogress;
        MaxDownloadCount = downLoad.Count;
        m_WaitDownloadFileList.AddRange(downLoad);
        OnSortDownLoadList();
        OnStartTask();
    }

    private void OnAddDownLoadTask(stDownLoadFileInfo fileinfo)
    {
        m_WaitDownloadFileList.Add(fileinfo);
        OnSortDownLoadList();
    }

    private void OnStartTask()
    {
        int waitdownloadcount = m_WaitDownloadFileList.Count;
        if (waitdownloadcount > 0)
        {
            if (m_CanUseTaskCount > 0)
            {
                int downloadCount = m_CanUseTaskCount > waitdownloadcount ? waitdownloadcount : m_CanUseTaskCount;
                for (int i = 0; i < downloadCount; i++)
                {
                    stDownLoadFileInfo file = m_WaitDownloadFileList[0];
                    m_WaitDownloadFileList.RemoveAt(0);
                    OnStartDownLoadHandle(file);
                }
            }
            else
            {
                m_MemPool.ClearUnoccupiedPool();
            }
        }
        else
        {
            if (m_MemPool.UsingCount == 0)
            {
                //ȫ��������� ��֪ͨManager
                this.On_Taskfinish?.Invoke(this);
            }
           
        }
    }

    private void OnStartDownLoadHandle(stDownLoadFileInfo file)
    {
        //���Լ���
        bool isnew = false;
       
        HFDownLoadAssetHandle handle = m_MemPool.GetItem( out isnew); ;
      
        if (isnew)
        {
            handle.transform.SetParent(m_RootGameObject.transform);
        }
        handle.OnDownloadedCallaback += OnListenerDownloadCallBack;
        handle.StartDownload(file);
    }

    private void OnListenerDownloadCallBack(HFDownLoadAssetHandle handle)
    {
        if (handle.Success)
        {
            DownloadedCount++;
            OnSendDownLoadAssetCallback(handle);
        }
        else
        {
            OnFailed(handle);
        }
        m_MemPool.GiveBack(handle);
        OnStartTask();
    }

    private void OnSendDownLoadAssetCallback(HFDownLoadAssetHandle handle)
    {
        DownLoadedInfo info = new DownLoadedInfo();
        info.data = handle.data;
        info.FileInfo = handle.fileInfo;
        info.Success = handle.Success;
        On_DownLoadCallBack?.Invoke(info);
        DownLoadProgress loadProgress = new DownLoadProgress();
        loadProgress.DownloadedCount= DownloadedCount;
        loadProgress.Max = m_MaxTask;
        On_DownLoadProgress?.Invoke(loadProgress);
    }

    /// <summary>
    /// ����ʧ�ܴ���
    /// </summary>
    /// <param name="handle"></param>
    private void OnFailed(HFDownLoadAssetHandle handle)
    {
        stDownLoadFileInfo info = handle.fileInfo;
        info.failedCount = info.failedCount + 1;
        info.Weight = EnGroupWeight.Normal; // ��Ϊʧ���ˣ����Խ��������ȼ�����Ȼ���׶����������
        if (info.failedCount < MaxFailedCount)
        {
            // ���»ص������� �ȴ��ٴμ���
            OnAddDownLoadTask(info);
        }
        else
        {
            //�ļ��޷����� ��ֱ�ӷ���
            FailedFile.Add(info);
            DownloadedCount++;
            OnSendDownLoadAssetCallback(handle);
        }

    }

    private void OnSortDownLoadList()
    {
        if (m_WaitDownloadFileList.Count > 2)
        {
            m_WaitDownloadFileList.Sort((a, b) =>
            {
                int Aindex = a.Weight == EnGroupWeight.High ? 100 : 0 + MaxFailedCount - a.failedCount;
                int Bindex = b.Weight == EnGroupWeight.High ? 100 : 0 + MaxFailedCount - b.failedCount;

                return Aindex > Bindex ? 1 : -1;
            });
        }
    }

    public void OnClear() {
        m_MemPool.ClearUnoccupiedPool();
        m_MemPool.Clearm_UsingPoolPool();
        m_WaitDownloadFileList.Clear();
        FailedFile.Clear();
        On_DownLoadCallBack = null;
        On_DownLoadProgress = null;
    }

    public void Recycle()
    {
        m_MemPool.Recycle();
        m_WaitDownloadFileList.Clear();
        FailedFile.Clear();
        m_WaitDownloadFileList= null;
        m_RootGameObject.transform.parent = null;
        GameObject.Destroy(m_RootGameObject);
        On_DownLoadCallBack = null;
        On_DownLoadProgress = null;
        On_Taskfinish = null;
    }
}